package avicit.bdp.dms.das.service;


import avicit.bdp.common.base.BaseService;
import avicit.bdp.common.service.dto.BdpTableDTO;
import avicit.bdp.common.utils.BdpLogUtil;
import avicit.bdp.common.utils.CheckParaUtils;
import avicit.bdp.common.utils.enums.StatusEnums;
import avicit.bdp.core.constant.Constants;
import avicit.bdp.dms.das.dao.LayerDAO;
import avicit.bdp.dms.das.dto.LayerDTO;
import avicit.platform6.api.system.ConvertColumnClient;
import avicit.platform6.api.system.impl.SystemConstant;
import avicit.platform6.commons.utils.BusinessUtil;
import avicit.platform6.commons.utils.ComUtil;
import avicit.platform6.core.exception.BusinessException;
import avicit.platform6.core.properties.PlatformConstant;
import avicit.platform6.core.rest.msg.QueryRespBean;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;


/**
 * @author yangpf
 * 数据分层表服务
 */
@Transactional
@Service
public class LayerService extends BaseService<LayerDAO, LayerDTO> {

    @Autowired
    private ConvertColumnClient convertColumnClient;

    @Autowired
    private BdpDasTableService bdpDasTableService;

    /**
     * 新增数据分层对象
     *
     * @param layerDTO
     * @return
     */
    public String insertLayer(LayerDTO layerDTO) {
        checkNameUnique(layerDTO);

        checkCodeUnique(layerDTO);

        CheckParaUtils.checkIntegerValidity(layerDTO.getOrderBy(), logger, "排序号必填");

        layerDTO.setId(ComUtil.getId());
        layerDTO.setStatus(StatusEnums.STOP.getCode());
        insertSelective(layerDTO);

        BdpLogUtil.log4Insert(layerDTO);
        return layerDTO.getId();
    }

    public void updateLayer(LayerDTO layerDTO) {
        CheckParaUtils.checkStringValidity(layerDTO.getName(), logger, "名称必填");
        CheckParaUtils.checkStringValidity(layerDTO.getCode(), logger, "编码必填");
        CheckParaUtils.checkIntegerValidity(layerDTO.getOrderBy(), logger, "排序号必填");

        LayerDTO oldLayerDTO = this.selectByPrimaryKey(layerDTO.getId());
        CheckParaUtils.checkDbObjectValidity(oldLayerDTO, logger,
                String.format("没有查到数据，请确保id:%s的数据是否存在", layerDTO.getId()));

        if (oldLayerDTO.getStatus() != null && oldLayerDTO.getStatus() == StatusEnums.RUNNING.getCode()) {
            throw new BusinessException("该数据分层已启用，不能编辑!");
        }

        // 校验标准名称唯一性
        if (!layerDTO.getName().equals(oldLayerDTO.getName())) {
            checkNameUnique(layerDTO);
        }

        // 校验标准编码唯一性
        if (!layerDTO.getCode().equals(oldLayerDTO.getCode())) {
            checkCodeUnique(layerDTO);
        }

        layerDTO.setCreationDate(oldLayerDTO.getCreationDate());
        this.updateByPrimaryKey(layerDTO);
        BdpLogUtil.log4Update(layerDTO, oldLayerDTO);
    }

    /**
     * 删除数据分层
     *
     * @param id
     * @return
     */
    public Boolean deleteLayer(String id) {
        CheckParaUtils.checkStringValidity(id, logger, "没有传入待删除的ID");
        LayerDTO layerDTO = this.selectByPrimaryKey(id);
        CheckParaUtils.checkDbObjectValidity(layerDTO, logger,
                String.format("没有查到数据，请确保id:%s的数据是否存在", id));
        if (layerDTO.getStatus() != null && layerDTO.getStatus() == StatusEnums.RUNNING.getCode()) {
            throw new BusinessException("该数据分层已启用，不能删除!");
        }
        // 判断数据分层是否被引用
        BdpTableDTO layerQuery = new BdpTableDTO();
        layerQuery.setLayerId(id);
        List<BdpTableDTO> list = bdpDasTableService.selectList(layerQuery);
        if(CollectionUtils.isNotEmpty(list)){
            throw new BusinessException("该数据分层已被引用，不能删除!");
        }

        this.mapper.deleteByPrimaryKey(id);
        // 记录日志
        BdpLogUtil.log4Delete(layerDTO);
        return true;
    }

    /**
     * 分页查询数据分层
     *
     * @param keyWords
     * @param status
     * @param pageNo
     * @param pageSize
     * @return
     */
    public QueryRespBean<LayerDTO> getPageList(String keyWords, Integer status, Integer pageNo, Integer pageSize) {
        QueryRespBean<LayerDTO> queryRespBean = new QueryRespBean<>();
        PageHelper.startPage(pageNo, pageSize);

        Page<LayerDTO> page = this.mapper.getPageList(keyWords, status);
        try {
            valueConvert(page);
        } catch (Exception e) {
            e.printStackTrace();
        }
        queryRespBean.setResult(page);
        BdpLogUtil.log4Query(queryRespBean);
        return queryRespBean;
    }

    private void valueConvert(Page<LayerDTO> page) {
        //循环组装请求数据
        Map<String, Set<String>> convertFormData = new HashMap<>(16);
        for (LayerDTO layerDTO : page) {
            BusinessUtil.createConvertSet(convertFormData, SystemConstant.USER, layerDTO.getCreatedBy());
            BusinessUtil.createConvertSet(convertFormData, Constants.BDP_DATA_SECRET_LEVEL_KEY, layerDTO.getSecretLevel());
        }
        if (convertFormData.size() > 0) {
            //获取请求结果
            Map<String, Map<String, String>> convertResultData = convertColumnClient.replace(convertFormData);
            //循环设置Alias或Name的值
            for (LayerDTO layerDTO : page) {
                layerDTO.setStatusString(StatusEnums.getDescByCode(layerDTO.getStatus()));
                layerDTO.setCreatedBy(BusinessUtil.convertFormat(convertResultData, SystemConstant.USER,
                        layerDTO.getCreatedBy()));
                layerDTO.setSecretLevelName(BusinessUtil.convertFormat(
                        convertResultData, Constants.BDP_DATA_SECRET_LEVEL_KEY, layerDTO.getSecretLevel()));
            }
        }
    }

    /**
     * 校验名称唯一性
     *
     * @param layerDTO 检测对象
     */
    private void checkNameUnique(LayerDTO layerDTO) {
        if (layerDTO != null) {
            if (StringUtils.isEmpty(layerDTO.getName())) {
                throw new BusinessException("名称不能为空");
            }

            LayerDTO paramName = new LayerDTO();
            paramName.setName(layerDTO.getName());
            if (this.selectCount(paramName) > 0) {
                throw new BusinessException("名称[" + layerDTO.getName() + "]已存在");
            }
        }
    }

    /**
     * 校验名称和代码唯一性
     *
     * @param layerDTO 检测对象
     */
    private void checkCodeUnique(LayerDTO layerDTO) {
        if (layerDTO != null) {
            if (StringUtils.isEmpty(layerDTO.getCode())) {
                throw new BusinessException("代码不能为空");
            }

            LayerDTO paramCode = new LayerDTO();
            paramCode.setCode(layerDTO.getCode());
            if (this.selectCount(paramCode) > 0) {
                throw new BusinessException("编码[" + layerDTO.getCode() + "]已存在");
            }
        }
    }

    public LayerDTO queryById(String id) {
        LayerDTO layerDTO = this.selectByPrimaryKey(id);
        CheckParaUtils.checkDbObjectValidity(layerDTO, logger,
                String.format("没有查到数据，请确保id:%s的数据是否存在", id));

        layerDTO.setStatusString(StatusEnums.getDescByCode(layerDTO.getStatus()));
        return layerDTO;
    }


    public void updateStatus(String id, Integer status) {
        CheckParaUtils.checkStringValidity(id, logger, "没有传入待启用/停用的ID");

        LayerDTO layerDTO = this.selectByPrimaryKey(id);
        CheckParaUtils.checkDbObjectValidity(layerDTO, logger, String.format("没有查到数据，请确保id:%s的资源分层是否存在", id));

        // 修改状态
        layerDTO.setStatus(status);

        String logTitle = "";
        if (status == 0) {
            logTitle = "停用数据分层：【";
        } else {
            logTitle = "启用数据分层：【";
        }
        logTitle += layerDTO.getName() + "】";
        BdpLogUtil.log("数据分层模块", logTitle, PlatformConstant.OpType.update);
        this.updateByPrimaryKeySelective(layerDTO);
    }

    public List<LayerDTO> selectLayerList() {
        LayerDTO query = new LayerDTO();
        query.setStatus(StatusEnums.RUNNING.getCode());
        return this.selectList(query).stream()
                .sorted(Comparator.comparing(LayerDTO::getOrderBy))
                .collect(Collectors.toList());
    }
}
